﻿using HDS.Admin.Api.ViewModels.Distributor;
using HDS.Common.Helper;
using HDS.IService.DistributorApi;
using HDS.IService.Log;
using HDS.IService.Master;
using HDS.Model;
using HDS.Model.Entity.Master;
using HDS.Model.Entity.View;
using LinqKit;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace HDS.Admin.Api.Controllers
{
    [Route("distributor/[action]")]
    [ApiController]
    [EnableCors]
    [Authorize]
    public class DistributorController : AdminController
    {
        private readonly ILogger<DistributorController> _logger;
        private readonly IHotelService _IHotelService;
        private readonly IDistributorService _IDistributorService;
        private readonly IUpdateLogService _IUpdateLogService;
        private readonly IDistributorApiService _IDistributorApiService;

        public DistributorController(ILogger<DistributorController> logger, IHotelService ihotelService, IDistributorService idistributorConfigService, IUpdateLogService iupdateLogService, IDistributorApiService idistributorApiService)
        {
            _logger = logger;
            _IHotelService = ihotelService;
            _IDistributorService = idistributorConfigService;
            _IUpdateLogService = iupdateLogService;
            _IDistributorApiService = idistributorApiService;
        }

        public async Task<ResultData<DataPagingModel<VDistributorHotel>>> GetHotelList([FromBody] SearchDto searchDto)
        {
            var hotelNameEn = (searchDto.HotelName ?? "").IsEnglish() ? searchDto.HotelName : "";
            var hotelNameCn = (searchDto.HotelName ?? "").IsEnglish() ? "" : searchDto.HotelName;

            var predicate = PredicateBuilder.New<VDistributorHotel>(true);
            var whereSql = "";
            if (searchDto.HotelId.HasValue)
                predicate = predicate.And(e => e.HotelId == searchDto.HotelId);
            if (searchDto.HotelStar.HasValue)
                predicate = predicate.And(e => e.HotelStar == searchDto.HotelStar);
            if (!string.IsNullOrEmpty(hotelNameEn))
            {
                var name = "+" + hotelNameEn.Trim().RemoveNotLetterNumber().ReplaceMultSpaceToOne().Replace(" ", " +");
                whereSql = "MATCH(hotel_name_en) AGAINST('" + name.Trim().FilterSql() + "' IN BOOLEAN MODE)";
            }
            if (!string.IsNullOrEmpty(hotelNameCn))
                predicate = predicate.And(e => e.HotelNameCn.Contains(hotelNameCn.Trim()));
            if (!string.IsNullOrEmpty(searchDto.CountryName))
                predicate = predicate.And(e => e.CountryName.Contains(searchDto.CountryName.Trim()));
            if (!string.IsNullOrEmpty(searchDto.CityName))
                predicate = predicate.And(e => e.CityName.Contains(searchDto.CityName.Trim()));
            if (!string.IsNullOrEmpty(searchDto.Distributor)) 
                predicate = predicate.And(e => e.Distributor.Equals(searchDto.Distributor));
            if (!string.IsNullOrEmpty(searchDto.DistributorHotelId))
                predicate = predicate.And(e => e.DistributorHotelId.Equals(searchDto.DistributorHotelId));
            if (searchDto.Isonline.HasValue)
                predicate = predicate.And(e => e.Isonline.Equals(searchDto.Isonline.Value));
            if (searchDto.PushStatus.HasValue)
                predicate = predicate.And(e => e.PushStatus.Equals(searchDto.PushStatus.Value));
            if (searchDto.PushResult.HasValue)
                predicate = predicate.And(e => e.PushResult.Equals(searchDto.PushResult.Value));

            var dataPaging = await _IDistributorService.GetHotelList(searchDto.PageIndex, searchDto.PageSize, predicate, whereSql);

            return new ResultData<DataPagingModel<VDistributorHotel>> { Success = true, Data = dataPaging };
        }

        public async Task<ResultData<int>> AddHotels([FromBody] DHotelsDto addHotelDto)
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var userName = User.FindFirstValue(ClaimTypes.Name);

            foreach (var distributor in addHotelDto.Distributors)
            {
                await _IDistributorService.AddHotels(distributor, addHotelDto.HotelIds, addHotelDto.HotelMd5s, userId, userName, DateTime.Now);
            }

            return new ResultData<int> { Success = true, Data = 0 };
        }

        public async Task<ResultData<int>> SetCities([FromBody] SetCityDto setCityDto)
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var userName = User.FindFirstValue(ClaimTypes.Name);

            foreach (var hotelId in setCityDto.HotelIds)
            {
                await _IDistributorService.SetCity(setCityDto.Distributor, hotelId, setCityDto.DistributorCityId, setCityDto.DistributorCityName, userId, userName, DateTime.Now);
            }

            return new ResultData<int> { Success = true, Data = 0 };
        }

        public async Task<ResultData<int>> SetOnline([FromBody] DHotelsDto hotelsDto)
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var userName = User.FindFirstValue(ClaimTypes.Name);

            await _IDistributorService.SetOnline(hotelsDto.Distributors, hotelsDto.HotelIds, userId, userName, DateTime.Now);

            return new ResultData<int> { Success = true, Data = 0 };
        }

        public async Task<ResultData<int>> SetOffline([FromBody] DHotelsDto hotelsDto)
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var userName = User.FindFirstValue(ClaimTypes.Name);

            await _IDistributorService.SetOffline(hotelsDto.Distributors, hotelsDto.HotelIds, userId, userName, DateTime.Now);

            return new ResultData<int> { Success = true, Data = 0 };
        }

        public async Task<ResultData<VDistributorHotel>> GetHotel(string distributor, int hotelId)
        {
            return new ResultData<VDistributorHotel> { Success = true, Data = await _IDistributorService.GetHotel(distributor, hotelId) };
        }

        public async Task<ResultData<List<VDistributorRoom>>> GetRoomList(string distributor, int hotelId)
        {
            return new ResultData<List<VDistributorRoom>> { Success = true, Data = await _IDistributorService.GetRoomList(distributor, hotelId) };
        }



        public async Task<ResultData<List<DistributorConfig>>> GetConfigList()
        {
            return new ResultData<List<DistributorConfig>> { Success = true, Data = await _IDistributorService.GetConfigList(e => true) };
        }

        public async Task<ResultData<int>> SaveConfig([FromBody] ConfigDto configDto)
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var userName = User.FindFirstValue(ClaimTypes.Name);

            await _IDistributorService.SaveConfig(configDto.Distributor, configDto.Isonline, configDto.Remark, userId, userName, DateTime.Now);

            return new ResultData<int> { Success = true, Data = 0 };
        }



        public async Task<ResultData<List<DistributorSupplierSetting>>> GetSupplierSettingList(string distributor, string supplier)
        {
            var predicate = PredicateBuilder.New<DistributorSupplierSetting>(true);
            if (!string.IsNullOrEmpty(distributor))
                predicate = predicate.And(e => e.Distributor.Equals(distributor));
            if (!string.IsNullOrEmpty(supplier))
                predicate = predicate.And(e => e.Supplier.Equals(supplier));

            var data = await _IDistributorService.GetSupplierSettingList(predicate);

            return new ResultData<List<DistributorSupplierSetting>> { Success = true, Data = data };
        }

        public async Task<ResultData<int>> SaveSupplierSetting([FromBody] DistributorSupplierSetting entity)
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var userName = User.FindFirstValue(ClaimTypes.Name);

            entity.UpdatedBy = userId;
            entity.UpdatedByName = userName;
            entity.UpdatedTime = DateTime.Now;

            await _IDistributorService.SaveSupplierSetting(entity);

            return new ResultData<int> { Success = true, Data = 0 };
        }



        public async Task<ResultData<List<DistributorHotelSetting>>> GetHotelSettingList(string distributor, int? hotelId)
        {
            var predicate = PredicateBuilder.New<DistributorHotelSetting>(true);
            if (!string.IsNullOrEmpty(distributor))
                predicate = predicate.And(e => e.Distributor.Equals(distributor));
            if (hotelId.HasValue)
                predicate = predicate.And(e => e.HotelId.Equals(hotelId));

            var data = await _IDistributorService.GetHotelSettingList(predicate);

            return new ResultData<List<DistributorHotelSetting>> { Success = true, Data = data };
        }

        public async Task<ResultData<int>> SaveHotelSetting([FromBody] DistributorHotelSetting entity)
        {
            var userId = Convert.ToInt32(User.FindFirstValue(ClaimTypes.Sid));
            var userName = User.FindFirstValue(ClaimTypes.Name);

            entity.UpdatedBy = userId;
            entity.UpdatedByName = userName;
            entity.UpdatedTime = DateTime.Now;

            await _IDistributorService.SaveHotelSetting(entity);

            return new ResultData<int> { Success = true, Data = 0 };
        }

        public async Task<ResultData<int>> DeleteHotelSetting(int hotelId, string distributor, string supplier)
        {
            await _IDistributorService.DeleteHotelSetting(hotelId, distributor, supplier);

            return new ResultData<int> { Success = true, Data = 0 };
        }



        public async Task<ResultData<string>> PushHotelInfo(string distributor, int hotelId)
        {
            await _IDistributorApiService.InitConfig(distributor);
            return await _IDistributorApiService.PushHotelInfo(hotelId, false, this.UserId, this.UserName);
        }
        public async Task<ResultData<string>> PushDeleteHotel(string distributor, int hotelId)
        {
            await _IDistributorApiService.InitConfig(distributor);
            return await _IDistributorApiService.PushDeleteHotel(hotelId, this.UserId, this.UserName);
        }
        public async Task<ResultData<string>> PushRoomInfo(string distributor, int hotelId)
        {
            await _IDistributorApiService.InitConfig(distributor);
            return await _IDistributorApiService.PushRoomInfo(hotelId, false, this.UserId, this.UserName);
        }
        public async Task<ResultData<string>> QueryPushResult(string distributor, int hotelId)
        {
            await _IDistributorApiService.InitConfig(distributor);
            return await _IDistributorApiService.QueryPushResult(hotelId, this.UserId, this.UserName);
        }
    }
}
